/**
 * 通用函数
 * @date 2024.9.10
 * @author wz
 */
import { _decorator, AnimationClip, Asset, Camera, Component, Constructor, Director, director, find, ImageAsset, isValid, Node, RenderTexture, resources, size, SpriteFrame, Texture2D, tween, UITransform, Vec2, Vec3, view, Widget } from 'cc';

export class Utils {
    /**
     * 生成一个uuid
     * @returns 
     */
    static uuid() {
        var len = 32;      //32长度
        var radix = 16;    //16进制
        var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
        var uuid = [], i;
        radix = radix || chars.length;
        if (len) {
            for (i = 0; i < len; i++) {
                uuid[i] = chars[0 | Math.random() * radix];
            }
        } else {
            var r;
            uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
            uuid[14] = '4';
            for (i = 0; i < 36; i++) {
                if (!uuid[i]) {
                    r = 0 | Math.random() * 16;
                    uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
                }
            }
        }
        return uuid.join('');
    }




    /**
     * 将输入的字符串转换为 UTF-8 编码的字节序列。
     * 如 Hello, 世界! ==> "Hello, \xE4\xB8\x96\xE7\x95\x8C!"
     * @param string 
     * @returns 
     */
    public static utf8Encode (string: string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";
        for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                utftext += String.fromCharCode(c);
            } else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            } else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }
        return utftext;
    }

    /**
     * 将 UTF-8 编码的字节序列解码为原始的字符串
     * 如 "Hello, \xE4\xB8\x96\xE7\x95\x8C! ==> Hello, 世界!"
     * @param utftext 
     * @returns 
     */
    public static utf8Decode (utftext: string) {
        var string = "";
        var i = 0;
        var c = 0;
        var c1 = 0;
        var c2 = 0;
        var c3 = 0;
        while ( i < utftext.length ) {
            c = utftext.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            } else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            } else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }

    /**
     * base64编码
     * @param input 
     * @returns 
     */
    public static base64encode (input: string) {
        var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        var output = "", chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;
        input = this.utf8Encode(input);
        while (i < input.length) {
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
            output = output +
                keyStr.charAt(enc1) + keyStr.charAt(enc2) +
                keyStr.charAt(enc3) + keyStr.charAt(enc4);
        }
        return output;
    }

    /**
     * base64解码
     * @param input 
     * @returns 
     */
    public static base64Decode (input: string) {
        var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        var output = "";
        var chr1;
        var chr2;
        var chr3;
        var enc1;
        var enc2;
        var enc3;
        var enc4;
        var i = 0;
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
        while (i < input.length) {
            enc1 = keyStr.indexOf(input.charAt(i++));
            enc2 = keyStr.indexOf(input.charAt(i++));
            enc3 = keyStr.indexOf(input.charAt(i++));
            enc4 = keyStr.indexOf(input.charAt(i++));
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
            output = output + String.fromCharCode(chr1);
            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
        }
        output = this.utf8Decode(output);
        return output;
    }

    /**
     * 通过动画剪辑获取插值数据
     * @param clip 
     * @param t 
     * @param trackIndex 
     * @param channelIndex 
     * @returns 
     */
    static getCurveByTracks(clip: AnimationClip, t: number, trackIndex: number = 0, channelIndex: number = 0) {
        let track = clip.getTrack(trackIndex)
        let channel = track.channels()[channelIndex]
        let curve = channel.curve
        return curve.evaluate(t)
    }

    /**
     * 判断节点是否有效(调用了destroy之后无效)
     * @param node 
     * @returns 
     */
    static isValidNode(node: Node) {
        return node && node.isValid && isValid(node, true);
    }

    /**
     * 创建节点
     * @param name
     */
    static createNode(name: string, parent?: Node) {
        let node = null;
        const root = parent ?? director.getScene()?.getChildByName('Canvas')
        if (root) {
            node = new Node(name);
            root!.addChild(node);
            node.setPosition(Vec3.ZERO);
            const w = node.addComponent(Widget);
            w.isAlignTop = w.isAlignBottom = w.isAlignLeft = w.isAlignRight = true;
            w.top = w.bottom = w.left = w.right = 0;
            w.updateAlignment();
        }
        else console.warn('canvas is null')
        return node;
    }
    /**
     * @param captureCamera 
     * @param x 
     * @param y 
     * @param w 需要整数！
     * @param h 需要整数！
     * @param rt 是否翻转图片（截图默认是反过来的，翻转会比较慢 可以改用node.scaleY = -1
     * @returns 
     */
    static screenShot(captureCamera: Camera, x: number, y: number, w: number, h: number, rt?: boolean) {
        return new Promise<SpriteFrame>(async (resolve) => {
            const viewSize = view.getVisibleSize();
            const width = w || view.getVisibleSize().width;
            const height = h || view.getVisibleSize().height;

            const sf = new SpriteFrame();
            const renderTexture = new RenderTexture();
            renderTexture.reset({
                width: viewSize.width,
                height: viewSize.height,
            });
            captureCamera.targetTexture = renderTexture;

            //等待渲染后
            await new Promise((r) => {
                director.once(Director.EVENT_AFTER_DRAW, r);
            });

            let buffer = renderTexture.readPixels(x || 0, y || 0, width, height);
            let rtBuffer = buffer;
            if (rt) {
                rtBuffer = new Uint8Array(width * height * 4);
                for (let i = height - 1; i >= 0; i--) {
                    for (let j = 0; j < width; j++) {
                        rtBuffer[((height - 1 - i) * (width) + j) * 4 + 0] = buffer[(i * width + j) * 4 + 0];
                        rtBuffer[((height - 1 - i) * (width) + j) * 4 + 1] = buffer[(i * width + j) * 4 + 1];
                        rtBuffer[((height - 1 - i) * (width) + j) * 4 + 2] = buffer[(i * width + j) * 4 + 2];
                        rtBuffer[((height - 1 - i) * (width) + j) * 4 + 3] = buffer[(i * width + j) * 4 + 3];
                    }
                }
            }
            const image = new ImageAsset({
                _data: rtBuffer,
                _compressed: false,
                width,
                height,
                format: Texture2D.PixelFormat.RGBA8888,
            });
            const t = new Texture2D();
            t.image = image;
            sf.texture = t;
            captureCamera.targetTexture = null;
            resolve(sf);
        })
    }


    // // 开始震动
    // public static shakeScreen(shakeNode:Node ,duration: number = 0.2, strength: number = 100, frequency: number = 10): void {
    //     //初始位置
    //     const initPos = shakeNode.position.clone();

    //     // 计算每次震动的时间间隔
    //     const interval = duration / frequency;

    //     // 创建一个震动动画
    //     const shakeAnimation = tween(shakeNode)
    //         .sequence(
    //             ...Array.from({ length: frequency }, (_, i) => {
    //                 const direction = i % 2 === 0 ? 1 : -1;
    //                 return tween()
    //                     .by(interval / 2, new Vec2(strength * direction, 0))
    //                     .by(interval / 2, new Vec2(-strength * direction, 0));
    //             })
    //         )
    //         .call(() => {
    //             // 震动结束后重置位置
    //             shakeNode!.position = initPos;
    //         })
    //         .start();
    // }
}